home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / wnos / wn941101 / cmdparse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-10  |  6.8 KB  |  350 lines

  1. /* Parse command line, set up command arguments Unix-style, and call function.
  2.  * Note: argument is modified (delimiters are overwritten with nulls)
  3.  * Improved error handling by Brian Boesch of Stanford University
  4.  */
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include "global.h"
  8. #include "proc.h"
  9. #include "cmdparse.h"
  10.  
  11. static char * near
  12. stringparse(line)
  13. char *line;
  14. {
  15.     char *cp = line;
  16.     unsigned long num;
  17.  
  18.     while ( *line != '\0' && *line != '\"' ) {
  19.         if ( *line == '\\' ) {
  20.             line++;
  21.             switch ( *line++ ) {
  22.             case 'n':
  23.                 *cp++ = '\n';
  24.                 break;
  25.             case 't':
  26.                 *cp++ = '\t';
  27.                 break;
  28.             case 'v':
  29.                 *cp++ = '\v';
  30.                 break;
  31.             case 'b':
  32.                 *cp++ = '\b';
  33.                 break;
  34.             case 'r':
  35.                 *cp++ = '\r';
  36.                 break;
  37.             case 'f':
  38.                 *cp++ = '\f';
  39.                 break;
  40.             case 'a':
  41.                 *cp++ = '\a';
  42.                 break;
  43.             case '\\':
  44.                 *cp++ = '\\';
  45.                 break;
  46.             case '\?':
  47.                 *cp++ = '\?';
  48.                 break;
  49.             case '\'':
  50.                 *cp++ = '\'';
  51.                 break;
  52.             case '\"':
  53.                 *cp++ = '\"';
  54.                 break;
  55.             case 'x':
  56.                 num = strtoul( --line, &line, 16 );
  57.                 *cp++ = (char) num;
  58.                 break;
  59.             case '0':
  60.             case '1':
  61.             case '2':
  62.             case '3':
  63.             case '4':
  64.             case '5':
  65.             case '6':
  66.             case '7':
  67.                 num = strtoul( --line, &line, 8 );
  68.                 *cp++ = (char) num;
  69.                 break;
  70.             case '\0':
  71.                 return NULLCHAR;
  72.             default:
  73.                 *cp++ = *(line - 1);
  74.                 break;
  75.             };
  76.         } else {
  77.             *cp++ = *line++;
  78.         }
  79.     }
  80.  
  81.     if ( *line == '\"' )
  82.         line++;     /* skip final quote */
  83.     *cp = '\0';        /* terminate string */
  84.     return line;
  85. }
  86.  
  87. int
  88. cmdparse(cmds,line,p)
  89. struct cmds cmds[];
  90. char *line;
  91. void *p;
  92. {
  93.     struct cmds *cmdp;
  94.     char *argv[NARG], *cp, **pargv;
  95.     int argc, i;
  96.  
  97.     /* Remove cr/lf */
  98.     rip(line);
  99.  
  100.     for(argc = 0;argc < NARG;argc++)
  101.         argv[argc] = NULLCHAR;
  102.  
  103.     for(argc = 0;argc < NARG; ){
  104.         int qflag = FALSE;
  105.  
  106.         /* Skip leading white space */
  107.         while(*line == ' ' || *line == '\t')
  108.             line++;
  109.         if(*line == '\0')
  110.             break;
  111.         /* Check for quoted token */
  112.         if(*line == '"'){
  113.             line++;    /* Suppress quote */
  114.             qflag = TRUE;
  115.         }
  116.         argv[argc++] = line;    /* Beginning of token */
  117.  
  118.         if(qflag){
  119.             /* Find terminating delimiter */
  120.             if((line = stringparse(line)) == NULLCHAR){
  121.                 return -1;
  122.             }
  123.         } else {
  124.             /* Find space or tab. If not present,
  125.              * then we've already found the last
  126.              * token.
  127.              */
  128.             if((cp = strchr(line,' ')) == NULLCHAR
  129.              && (cp = strchr(line,'\t')) == NULLCHAR){
  130.                 break;
  131.             }
  132.             *cp++ = '\0';
  133.             line = cp;
  134.         }
  135.     }
  136.     if (argc < 1) {        /* empty command line */
  137.         argc = 1;
  138.         argv[0] = "";
  139.     }
  140.     /* Lines beginning with "#" are comments */
  141.     if(argv[0] == NULLCHAR || argv[0][0] == '#')
  142.         return 0;
  143.  
  144.     /* Look up command in table; prefix matches are OK */
  145.     for(cmdp = cmds;cmdp->name != NULLCHAR;cmdp++){
  146.         if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0)
  147.             break;
  148.     }
  149.     if(cmdp->name == NULLCHAR) {
  150.         if(cmdp->argc_errmsg != NULLCHAR) 
  151.             tprintf("%s\n",cmdp->argc_errmsg);
  152.         return -1;
  153.     } else {
  154.         if(argc < cmdp->argcmin) {
  155.             /* Insufficient arguments */
  156.             tprintf("Usage: %s\n",cmdp->argc_errmsg);
  157.             return -1;
  158.         } else {
  159.             if(cmdp->stksize == 0){
  160.                 return (*cmdp->func)(argc,argv,p);
  161.             } else {
  162.                 /* Make private copy of argv and args,
  163.                  * spawn off subprocess and return.
  164.                  */
  165.                 pargv = (char **)cxallocw(argc,sizeof(char *));
  166.                 for(i=0;i<argc;i++)
  167.                     pargv[i] = strxdup(argv[i]);
  168.                 newproc(cmdp->name,cmdp->stksize,
  169.                 (void (*)())cmdp->func,argc,pargv,p,1);
  170.                 return(0);
  171.             }
  172.         }
  173.     }
  174. }
  175.  
  176. /* Call a subcommand based on the first token in an already-parsed line */
  177. int
  178. subcmd(tab,argc,argv,p)
  179. struct cmds tab[];
  180. int argc;
  181. char *argv[];
  182. void *p;
  183. {
  184.     struct cmds *cmdp;
  185.     char **pargv;
  186.     int i, found = 0;
  187.  
  188.     /* Strip off first token and pass rest of line to subcommand */
  189.     if(argc < 1) {
  190.         tputs("SUBCMD - Don't know what to do\n");
  191.         return -1;
  192.     }
  193.     if(argc > 1) {
  194.         argc--;
  195.         argv++;
  196.         for(cmdp = tab; cmdp->name != NULLCHAR; cmdp++) {
  197.             if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0){
  198.                 found = 1;
  199.                 break;
  200.             }
  201.         }
  202.     }
  203.     if(!found) {
  204.         tputs("available subcommands:\n");
  205.         for(i = 0, cmdp = tab; cmdp->name != NULLCHAR; cmdp++, i = (i+1)%5)
  206.             tprintf("%-15.15s%s",cmdp->name,(i == 4) ? "\n" : "");
  207.  
  208.         if(i)
  209.             tputs("\n");
  210.         return -1;
  211.     }
  212.     if(argc < cmdp->argcmin){
  213.         if(cmdp->argc_errmsg != NULLCHAR)
  214.             tprintf("Usage: %s\n",cmdp->argc_errmsg);
  215.         return -1;
  216.     }
  217.     if(cmdp->stksize == 0){
  218.         return (*cmdp->func)(argc,argv,p);
  219.     } else {
  220.         /* Make private copy of argv and args */
  221.         pargv = (char **)cxallocw(argc,sizeof(char *));
  222.         for(i=0;i<argc;i++)
  223.             pargv[i] = strxdup(argv[i]);
  224.         newproc(cmdp->name,cmdp->stksize,
  225.          (void (*)())cmdp->func,argc,pargv,p,1);
  226.         return(0);
  227.     }
  228. }
  229.  
  230. /* Subroutine for setting and displaying boolean flags */
  231. int
  232. setbool(var,label,argc,argv)
  233. int *var;
  234. char *label;
  235. int argc;
  236. char *argv[];
  237. {
  238.     struct boolcmd {
  239.         char *str;    /* Token */
  240.         int val;    /* Value */
  241.     } Boolcmds[] = {
  242.         "y",        1,    /* Synonyms for "true" */
  243.         "yes",        1,
  244.         "true",        1,
  245.         "on",        1,
  246.         "1",        1,
  247.         "set",        1,
  248.         "enable",    1,
  249.  
  250.         "n",        0,    /* Synonyms for "false" */
  251.         "no",        0,
  252.         "false",    0,
  253.         "off",        0,
  254.         "0",        0,
  255.         "clear",    0,
  256.         "disable",    0,
  257.         NULLCHAR
  258.     };
  259.     struct boolcmd *bc;
  260.  
  261.     if(argc < 2){
  262.         tprintf("%s: %s\n",label,*var ? "on":"off");
  263.         return 0;
  264.     }
  265.     for(bc = Boolcmds; bc->str != NULLCHAR; bc++) {
  266.         if(strcmpi(argv[1],bc->str) == 0){
  267.             *var = bc->val;
  268.             return 0;
  269.         }
  270.     }
  271.     tputs("Valid options:");
  272.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
  273.         tprintf(" %s",bc->str);
  274.     tputs("\n");
  275.     return 1;
  276. }
  277.  
  278. /* Subroutine for setting and displaying long variables */
  279. int
  280. setlong(var,label,argc,argv)
  281. long *var;
  282. char *label;
  283. int argc;
  284. char *argv[];
  285. {
  286.     if(argc < 2)
  287.         tprintf("%s: %ld\n",label,*var);
  288.     else
  289.         *var = atol(argv[1]);
  290.  
  291.     return 0;
  292. }
  293.  
  294. /* Subroutine for setting and displaying short variables */
  295. int
  296. setshort(var,label,argc,argv)
  297. unsigned short *var;
  298. char *label;
  299. int argc;
  300. char *argv[];
  301. {
  302.     if(argc < 2)
  303.         tprintf("%s: %u\n",label,*var);
  304.     else
  305.         *var = atoi(argv[1]);
  306.  
  307.     return 0;
  308. }
  309.  
  310. /* Subroutine for setting and displaying integer variables */
  311. int
  312. setint(var,label,argc,argv)
  313. int *var;
  314. char *label;
  315. int argc;
  316. char *argv[];
  317. {
  318.     if(argc < 2)
  319.         tprintf("%s: %u\n",label,*var);
  320.     else
  321.         *var = atoi(argv[1]);
  322.  
  323.     return 0;
  324. }
  325.  
  326. /* Subroutine for setting and displaying int variables (with range check) */
  327. int
  328. setintrc(var, label, argc, argv, minval, maxval)
  329. int16 *var;
  330. char *label;
  331. int argc;
  332. char *argv[];
  333. int minval;
  334. int16 maxval;
  335. {
  336.     int tmp;
  337.  
  338.     if (argc < 2)
  339.         tprintf("%s: %u\n", label, *var);
  340.     else {
  341.         tmp = atoi(argv[1]);
  342.         if (isalpha(*argv[1]) || tmp < minval || tmp > maxval) {
  343.             tprintf("%s must be %i..%i\n", label, minval, maxval);
  344.             return 1;
  345.         }
  346.         *var = (int16)tmp;
  347.     }
  348.     return 0;
  349. }
  350.